/*   Copyright 2012 Julian Aloofi

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "DebugListener.hpp"

Tacticus::DebugListener *Tacticus::DebugListener::instance = 0;

Tacticus::DebugListener &Tacticus::DebugListener::getInstance()
{
    if (!instance)
        instance = new DebugListener();
    return *instance;
}

void Tacticus::DebugListener::destroy()
{
    if (instance)
        delete instance;
    instance = 0;
}

void Tacticus::DebugListener::handleEvent(boost::shared_ptr<Tacticus::Event>
    event)
{
    switch(event->getType())
    {
    case Events::PLACEMENT_EVENT:
    {
        boost::shared_ptr<PlacementEvent> placementEvent =
            boost::static_pointer_cast<PlacementEvent>(event);
        std::cout<<"PLACEMENT_EVENT occured. "<<
            placementEvent->getToPlace().str()<<": ("<<
            placementEvent->getWhereToPlace().x<<", "<<
            placementEvent->getWhereToPlace().y<<")"<<std::endl;
        break;
    }
    case Events::SUCCESSFULPLACEMENT_EVENT:
    {
        boost::shared_ptr<SuccessfulPlacementEvent> sucPlacementEvent =
            boost::static_pointer_cast<SuccessfulPlacementEvent>(event);
            std::cout<<"SUCCESSFULPLACEMENT_EVENT occured. "<<
                sucPlacementEvent->getSuccessfulEvent()->getToPlace().str()
                <<": ("<<
                sucPlacementEvent->getSuccessfulEvent()->getWhereToPlace().x
                <<", "<<
                sucPlacementEvent->getSuccessfulEvent()->getWhereToPlace().y
                <<")"<<std::endl;
        break;
    }
    case Events::QUITAPPLICATION_EVENT:
    {
        std::cout<<"QUITAPPLICATION_EVENT occured"<<std::endl;
        break;
    }
    case Events::NEWGAME_EVENT:
    {
        std::cout<<"NEWGAME_EVENT occured"<<std::endl;
        break;
    }
    case Events::STARTHOTSEAT_EVENT:
    {
        std::cout<<"STARTHOTSEAT_EVENT occured"<<std::endl;
        break;
    }
    case Events::PLACEMENTDONE_EVENT:
    {
        boost::shared_ptr<PlacementDoneEvent> succEv = boost::
            static_pointer_cast<PlacementDoneEvent>(event);
        std::cout<<"PLACEMENTDONE_EVENT occured for player "<<
            succEv->getDonePlayer().str()<<std::endl;
        break;
    }
    case Events::SUCCESSFULPLACEMENTDONE_EVENT:
    {
        boost::shared_ptr<SuccessfulPlacementDoneEvent> succEv = boost::
            static_pointer_cast<SuccessfulPlacementDoneEvent>(event);
        std::cout<<"SUCCESSFULPLACEMENTDONE_EVENT occured for player "<<
            succEv->getSuccessfulEvent()->getDonePlayer().str()<<std::endl;
        break;
    }
    case Events::SHUFFLEPLACEMENT_EVENT:
    {
        boost::shared_ptr<ShufflePlacementEvent> shuffEv = boost::
            static_pointer_cast<ShufflePlacementEvent>(event);
        std::cout<<"SHUFFLEPLACEMENT_EVENT occured for player "<<
            shuffEv->getWhichPlayer().str()<<std::endl;
        shufflePlacement(shuffEv->getWhichPlayer());
        break;
    }
    case Events::MAKETURN_EVENT:
    {
        boost::shared_ptr<MakeTurnEvent> mkTrnEv = boost::static_pointer_cast<
            MakeTurnEvent>(event);
        std::cout<<"MAKETURN_EVENT occured from "<<mkTrnEv->getWhereFrom().x<<
            ", "<<mkTrnEv->getWhereFrom().y<<" to "<<mkTrnEv->getWhereTo().x<<
            ", "<<mkTrnEv->getWhereTo().y<<std::endl;
        break;
    }
    case Events::SUCCESSFULTURN_EVENT:
    {
        boost::shared_ptr<SuccessfulTurnEvent> succEv =
            boost::static_pointer_cast<SuccessfulTurnEvent>(event);
        std::cout<<"SUCCESSFULTURN_EVENT occured, "<<
            succEv->getWhereFrom().second.str()<<" went from "<<
            succEv->getWhereFrom().first.x<<", "<<succEv->getWhereFrom().first.y
            <<" to "<<succEv->getWhereTo().first.x<<", "<<
            succEv->getWhereTo().first.y<<" ("<<
            succEv->getWhereTo().second.str()<<")"<<std::endl;
        break;
    }
    case Events::SHOWHOTSEATSWITCHDIALOG_EVENT:
    {
        std::cout<<"SHOWHOTSEATSWITCHDIALOG_EVENT occured"<<std::endl;
        break;
    }
    case Events::CONFIRMOKDIALOG_EVENT:
    {
        std::cout<<"CONFIRMOKDIALOG_EVENT occured"<<std::endl;
        break;
    }
    case Events::GAMEOVER_EVENT:
    {
        boost::shared_ptr<GameOverEvent> gOE = boost::static_pointer_cast<
            GameOverEvent>(event);
        std::cout<<"GAMEOVER_EVENT occured, "<<gOE->getWinner().str()<<" won."
            <<std::endl;
        break;
    }
    case Events::SHOWDRAWTURNSCREEN_EVENT:
    {
        boost::shared_ptr<ShowDrawTurnScreenEvent> sDTSE =
            boost::static_pointer_cast<ShowDrawTurnScreenEvent>(event);
        std::cout<<"SHOWDRAWTURNSCREEN_EVENT occured, drawing for turn "<<
            sDTSE->getOrigin().x<<", "<<sDTSE->getOrigin().y<<" to "<<
            sDTSE->getTarget().x<<", "<<sDTSE->getTarget().y<<std::endl;
        break;
    }
    default:
    {
        break;
    }
    }
}

void Tacticus::DebugListener::shufflePlacement(Tacticus::Player whichPlayer)
{
    int yOffset = 0;
    if (whichPlayer == RED)
        yOffset = 6;

    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            EventManager::getInstance().queueEvent(boost::shared_ptr<
                PlacementEvent>(new PlacementEvent(Field(NOBODY, EMPTY),
                Common::Coordinate(i, j + yOffset))));
        }
    }

    std::map<Piece, int> toBePlaced;
    toBePlaced[MARSHAL]     = 1;
    toBePlaced[GENERAL]     = 1;
    toBePlaced[COLONEL]     = 2;
    toBePlaced[MAJOR]       = 3;
    toBePlaced[CAPTAIN]     = 4;
    toBePlaced[LIEUTENANT]  = 4;
    toBePlaced[SERGEANT]    = 4;
    toBePlaced[MINER]       = 5;
    toBePlaced[SCOUT]       = 8;
    toBePlaced[SPY]         = 1;
    toBePlaced[BOMB]        = 6;
    toBePlaced[FLAG]        = 1;

    int xCount = 0, yCount = 0;

    if (whichPlayer == RED)
    {
        for (std::map<Piece, int>::reverse_iterator it = toBePlaced.rbegin();
            it != toBePlaced.rend(); it++)
        {
            for (int howMany = 0; howMany < it->second; howMany++)
            {
                EventManager::getInstance().queueEvent(boost::shared_ptr<
                    PlacementEvent>(new PlacementEvent(Field(whichPlayer,
                    it->first), Common::Coordinate(xCount, yCount + yOffset))));
                xCount++;
                if (xCount > 9)
                {
                    xCount = 0;
                    yCount++;
                }
            }
        }
    }
    else
    {
        for (std::map<Piece, int>::iterator it = toBePlaced.begin();
            it != toBePlaced.end(); it++)
        {
            for (int howMany = 0; howMany < it->second; howMany++)
            {
                EventManager::getInstance().queueEvent(boost::shared_ptr<
                    PlacementEvent>(new PlacementEvent(Field(whichPlayer,
                    it->first), Common::Coordinate(xCount, yCount + yOffset))));
                xCount++;
                if (xCount > 9)
                {
                    xCount = 0;
                    yCount++;
                }
            }
        }
    }
}
